package gu.jimgutil;

import java.nio.ByteBuffer;

import com.sun.jna.Platform;

import gu.jimgutil.jna.JimgutilLibrary;
/**
 * 图像矩阵转换/旋转native library实现
 * @author guyadong
 *
 */
class CsCvtNativeImpl extends BaseImageCvt{
	static final CsCvtNativeImpl NATIVE_IMPL = new CsCvtNativeImpl();
	private static boolean nativeLoaded = false;
	static{
		// load native library
		if(Platform.isAndroid() || Platform.isWindows() || Platform.isLinux() || Platform.isMac()){
			try {
				nativeLoaded = JimgutilLibrary.INSTANCE  != null;
			} catch (Throwable e) {
				System.out.println(e.getMessage());
			}
			
		}else{		
			System.out.println("native library UNSUPPORTED this platform");
		}
	}
	private CsCvtNativeImpl(){}
	/**
	 * native library是否加载成功
	 * @return 加载成功返回{@code true},否则返回{@code false}
	 */
	static boolean isNativeLoaded() {
		return nativeLoaded;
	}
	
	private static void checkError(int code){
		switch(code){
		case JimgutilLibrary.JIMGUTIL_OK:
			break;
		case JimgutilLibrary.JIMGUTIL_NULL_POINTER:
			throw new NullPointerException();
		case JimgutilLibrary.JIMGUTIL_INVALID_INPUT_SIZE:
			throw new IllegalArgumentException("INVALID INPUT SIZE");
		case JimgutilLibrary.JIMGUTIL_INVALID_OUTPUT_SIZE:
			throw new IllegalArgumentException("INVALID OUTPUT SIZE");
		case JimgutilLibrary.JIMGUTIL_INVALID_BPP:
			throw new IllegalArgumentException("INVALID bpp,available value:1,2,3,4");
		case JimgutilLibrary.JIMGUTIL_INVALID_ANGLE:
			throw new IllegalArgumentException("INVALID angle,available value:0,90,180,270");
		case JimgutilLibrary.JIMGUTIL_REQUIRED_EVEN_WH:
			throw new IllegalArgumentException("EVEN width and height required");
		case JimgutilLibrary.JIMGUTIL_INVALID_MATRIX_TYPE:
			throw new IllegalArgumentException("INVALID matrix type");
		case JimgutilLibrary.JIMGUTIL_INVALID_ARUGMENT:
		default:
			throw new IllegalArgumentException();
		}
	}
	private static void checkInputNotNull(byte[] input){
		if(input == null){
			throw new NullPointerException("input is null");
		}
	}
	private static void checkOutputNotNull(byte[] output){
		if(output == null){
			throw new NullPointerException("output is null");
		}
	}
	@Override
	void RGBA2BGR(byte[] input,int width,int height,int stride,byte[] output) 
			throws NullPointerException, IllegalArgumentException{	
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_RGBA2BGR(input, input.length, width, height, stride, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void RGBA2RGB(byte[] input,int width,int height,int stride,byte[] output) 
			throws NullPointerException, IllegalArgumentException{
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_RGBA2RGB(input, input.length, width, height, stride, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void RGBA2GRAY(byte[] input,int width,int height,int stride,byte[] output) 
			throws NullPointerException, IllegalArgumentException{
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_RGBA2GRAY(input, input.length, width, height, stride, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void RGB2BGR(byte[] input,int width,int height,int stride,byte[] output) 
			throws NullPointerException, IllegalArgumentException{
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_RGB2BGR(input, input.length, width, height, stride, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void swap3byte(byte[] input,int width,int height,int stride) 
			throws NullPointerException, IllegalArgumentException{
		checkInputNotNull(input);
		int code = JimgutilLibrary.INSTANCE.jimgutil_swap3byte(ByteBuffer.wrap(input), input.length, width, height, stride);
		checkError(code);	
	}
	@Override
	void RGB2GRAY(byte[] input,int width,int height,int stride,byte[] output) 
			throws NullPointerException, IllegalArgumentException{
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_RGB2GRAY(input, input.length, width, height, stride, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void BGR2RGBA(byte[] input,int width,int height,int stride,byte[] output) 
			throws NullPointerException, IllegalArgumentException{
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_BGR2RGBA(input, input.length, width, height, stride, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void RGB2RGBA(byte[] input,int width,int height,int stride,byte[] output) 
			throws NullPointerException, IllegalArgumentException{
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_RGB2RGBA(input, input.length, width, height, stride, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void rotate(byte[] input, int width, int height, int bpp, int angle) {
		checkInputNotNull(input);
		int code = JimgutilLibrary.INSTANCE.jimgutil_rotate(ByteBuffer.wrap(input), input.length, width, height, bpp, angle);
		checkError(code);	
	}
	@Override
	void hflip(byte[] input, int width, int height, int bpp) {
		checkInputNotNull(input);
		int code = JimgutilLibrary.INSTANCE.jimgutil_hflip(ByteBuffer.wrap(input), input.length, width, height, bpp);
		checkError(code);
	}
	@Override
	void vflip(byte[] input, int width, int height, int bpp) {
		checkInputNotNull(input);
		int code = JimgutilLibrary.INSTANCE.jimgutil_vflip(ByteBuffer.wrap(input), input.length, width, height, bpp);
		checkError(code);
	}
	@Override
	void NV212RGB(byte[] input, int width, int height, byte[] output) {
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_NV212RGB(input, input.length, width, height, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void NV212BGR(byte[] input, int width, int height, byte[] output) {
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_NV212BGR(input, input.length, width, height, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void NV212RGBA(byte[] input, int width, int height, byte[] output){
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_NV212RGBA(input, input.length, width, height, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void RGB2NV21(byte[] input, int width, int height, byte[] output){
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_RGB2NV21(input, input.length, width, height, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void BGR2NV21(byte[] input, int width, int height, byte[] output) {
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_BGR2NV21(input, input.length, width, height, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void RGBA2NV21(byte[] input, int width, int height, byte[] output){
		checkInputNotNull(input);
		checkOutputNotNull(output);
		int code = JimgutilLibrary.INSTANCE.jimgutil_RGBA2NV21(input, input.length, width, height, ByteBuffer.wrap(output), output.length);
		checkError(code);
	}
	@Override
	void nv21Rotate(byte[] input, int width, int height, int angle) {
		checkInputNotNull(input);
		int code = JimgutilLibrary.INSTANCE.jimgutil_nv21Rotate(ByteBuffer.wrap(input), input.length, width, height, angle);
		checkError(code);
	}
	@Override
	void nv21Hflip(byte[] input, int width, int height) {
		checkInputNotNull(input);
		int code = JimgutilLibrary.INSTANCE.jimgutil_nv21Hflip(ByteBuffer.wrap(input), input.length, width, height);
		checkError(code);
	}
	@Override
	void nv21Vflip(byte[] input, int width, int height) {
		checkInputNotNull(input);
		int code = JimgutilLibrary.INSTANCE.jimgutil_nv21Vflip(ByteBuffer.wrap(input), input.length, width, height);
		checkError(code);
	}
}
